﻿#include "pch.h"
#include "XiaoWeiHelper.h"

using namespace XiaoWeiHelpSDK;

System::String^ UTF8_To_Managed_Str(const wchar_t* w)
{
	System::String^ pStr = gcnew System::String(w);
	return pStr;
}
bool  XiaoWeiHelper::IsCoveredByOthers(CallBack^ cb)
{
	HWND xwWnd = ::FindWindowEx(NULL, NULL, NULL, L"惠小微");
	if (xwWnd == NULL) {
		if (cb != nullptr) {
			cb(L"NOT FOUND WINDOW");
		}
		return false;
	}

	if (::GetForegroundWindow() == xwWnd) {
		if (cb != nullptr) {
			cb(L"Xiowei is foreground");
			cb(L"NOTCOVERD");
		}
		return false;
	}

	RECT xwRC;
	GetWindowRect(xwWnd, &xwRC);


	if (xwRC.left < 0) {
		xwRC.left = 0;
	}
	if (xwRC.top < 0) {
		xwRC.top = 0;
	}
	RECT desktopRC;
	::SystemParametersInfo(SPI_GETWORKAREA, 0, &desktopRC, 0);
	if (xwRC.right > desktopRC.right) {
		xwRC.right = desktopRC.right;
	}
	if (xwRC.bottom > desktopRC.bottom) {
		xwRC.bottom = desktopRC.bottom;
	}


	int width = (xwRC.right - xwRC.left) / 10;
	int height = (xwRC.bottom - xwRC.top) / 5;
	xwRC.left += width;
	xwRC.right -= width;
	xwRC.top += height;
	xwRC.bottom -= height;

	wchar_t buf[256] = { 0 };
	swprintf(buf, 256, L"Xiaowei's rect %d,%d,%d,%d", xwRC.left, xwRC.right, xwRC.top, xwRC.bottom);
	if (cb != nullptr) {
		System::String^ s = UTF8_To_Managed_Str(buf);
		cb(s);
	}


	HRGN aboveRGN = ::CreateRectRgn(0, 0, 0, 0);

	HWND aboveWnd = xwWnd;

	while ((aboveWnd = ::GetNextWindow(aboveWnd, GW_HWNDPREV)) != NULL) {
		if (::IsWindowVisible(aboveWnd) &&
			IsWindow(aboveWnd) &&
			IsWindowEnabled(aboveWnd) &&
			!(GetWindowLong(aboveWnd, GWL_EXSTYLE) & WS_EX_TOOLWINDOW)) {
			//!(GetWindowLong(aboveWnd, GWL_EXSTYLE) & WS_EX_TOPMOST) {

			RECT rc;
			::GetWindowRect(aboveWnd, &rc);

			HRGN rgn = ::CreateRectRgn(rc.left, rc.top, rc.right, rc.bottom);
			int ret = CombineRgn(aboveRGN, aboveRGN, rgn, RGN_OR);
			::DeleteObject(rgn);
			if (ret == SIMPLEREGION || ret == COMPLEXREGION) {
				wchar_t name[256] = { 0 };
				wchar_t log[1024] = { 0 };
				wchar_t className[246] = { 0 };
				::GetClassName(aboveWnd, className, 256);
				::GetWindowText(aboveWnd, name, 256);
				swprintf(log, 1024, L"%s's rect %d,%d,%d,%d-%s", name, rc.left, rc.right, rc.top, rc.bottom, className);
				if (cb != nullptr) {
					System::String^ s = UTF8_To_Managed_Str(log);
					cb(s);
				}
			}
			else {
				wchar_t name[256] = { 0 };
				wchar_t log[1024] = { 0 };
				::GetWindowText(aboveWnd, name, 256);
				swprintf(log, 1024, L"%s's rect %d,%d,%d,%d NOT cover", name, rc.left, rc.right, rc.top, rc.bottom);
				if (cb != nullptr) {
					System::String^ s = UTF8_To_Managed_Str(log);
					cb(s);
				}
			}

			HRGN xwRGN = ::CreateRectRgn(xwRC.left, xwRC.top, xwRC.right, xwRC.bottom);
			ret = CombineRgn(xwRGN, xwRGN, aboveRGN, RGN_DIFF);
			::DeleteObject(xwRGN);
			if (ret == NULLREGION) {
				::DeleteObject(aboveRGN);
				if (cb != nullptr) {
					cb(L"COVERD");
				}
				return true;
			}
		}
		else {
			wchar_t name[256] = { 0 };
			wchar_t log[1024] = { 0 };
			::GetWindowText(aboveWnd, name, 256);
			swprintf(log, 1024, L"%s's rect  INVALID", name);
			if (cb != nullptr) {
				//cb(log);
			}
		}

	}


	::DeleteObject(aboveRGN);

	aboveWnd = ::GetForegroundWindow();
	if (aboveWnd != xwWnd) {
		wchar_t name[256] = { 0 };
		wchar_t className[256] = { 0 };
		wchar_t log[1024] = { 0 };
		RECT rc;
		::GetWindowText(aboveWnd, name, 256);
		::GetWindowRect(aboveWnd, &rc);
		::GetClassName(aboveWnd, className, 256);

		swprintf(log, 1024, L"%s's rect %d,%d,%d,%d ForgroudWindow-%s", name, rc.left, rc.right, rc.top, rc.bottom, className);
		if (cb != nullptr) {
			System::String^ s = UTF8_To_Managed_Str(log);
			cb(s);
		}

		if (wcscmp(className, L"Windows.UI.Core.CoreWindow") == 0 && wcscmp(name, L"搜索") == 0) {
			cb(L"Search window is foreground");
			rc.left = 0;
		}

		if (wcscmp(className, L"Progman") != 0) {
			if (rc.left <= xwRC.left &&
				rc.right >= xwRC.right &&
				rc.top <= xwRC.top
				&& rc.bottom >= xwRC.bottom) {

				cb(L"COVERD");
				return true;
			}
			else {
				cb(L"NOHit");
			}
		}
		else {
			cb(L"Desktop window, please ignore it");
		}
	}

	if (cb != nullptr) {
		cb(L"NOTCOVERD");
	}
	return false;
}

void  XiaoWeiHelper::RecoverPower(CallBack^ cb)
{
	if (powerHandle == NULL) {
		if (cb)
		{
			cb(L"RecoverPower NULL");
		}
		return;
	}
	//::PowerClearRequest(powerHandle, PowerRequestSystemRequired);
	::PowerClearRequest(powerHandle, PowerRequestDisplayRequired);
	::CloseHandle(powerHandle);
	powerHandle = NULL;
	if (cb) {
		cb(L"RecoverPower OK");
	}
}

void  XiaoWeiHelper::MaintainPower(CallBack^ cb)
{
	REASON_CONTEXT context;
	wchar_t* reasonBuf = new wchar_t[10];
	wcscpy(reasonBuf, L"Xiaowei");
	context.Flags = POWER_REQUEST_CONTEXT_SIMPLE_STRING;
	context.Version = POWER_REQUEST_CONTEXT_VERSION;
	context.Reason.SimpleReasonString = reasonBuf;
	powerHandle = ::PowerCreateRequest(&context);
	//BOOL bRet = ::PowerSetRequest(powerHandle, PowerRequestSystemRequired);
	BOOL bRet2 = ::PowerSetRequest(powerHandle, PowerRequestDisplayRequired);
	if (cb) {
		if (bRet2) {
			cb(L"MaintainPower OK");
		}
		else {
			cb(L"MaintainPower FAILED");
		}
	}
	delete[]reasonBuf;
}

bool  XiaoWeiHelper::IsCoveredByLockWindow(CallBack^ cb)
{
	HWND xwWnd = ::FindWindowEx(NULL, NULL, NULL, L"惠小微");
	if (xwWnd == NULL) {
		if (cb != nullptr) {
			cb(L"NOT FOUND WINDOW");
		}
		return false;
	}


	wchar_t name[256] = { 0 };
	wchar_t className[256] = { 0 };
	wchar_t log[1024] = { 0 };

	HWND hWnd = GetDesktopWindow();
	HMONITOR hMonitor = MonitorFromWindow(hWnd, MONITOR_DEFAULTTONEAREST);

	MONITORINFOEX miex;
	miex.cbSize = sizeof(miex);
	GetMonitorInfo(hMonitor, &miex);
	DEVMODE dm;
	dm.dmSize = sizeof(dm);
	dm.dmDriverExtra = 0;
	EnumDisplaySettings(miex.szDevice, ENUM_CURRENT_SETTINGS, &dm);
	int cxPhysical = dm.dmPelsWidth;
	int cyPhysical = dm.dmPelsHeight;

	swprintf(log, 1024, L"screen is %d %d", cxPhysical, cyPhysical);
	if (cb) {
		System::String^ s = UTF8_To_Managed_Str(log);
		cb(s);
	}


	HWND aboveWnd = ::GetForegroundWindow();

	if (aboveWnd == xwWnd) {
		if (cb) {
			cb(L"Not covered");
		}
		return false;
	}


	RECT rc;
	::GetWindowText(aboveWnd, name, 256);
	::GetWindowRect(aboveWnd, &rc);
	::GetClassName(aboveWnd, className, 256);

	int w = rc.right - rc.left;
	int h = rc.bottom - rc.top;
	if (w == cxPhysical && h == cyPhysical) {
		if (cb) {
			swprintf(log, 1024, L"Covered %s %d %d", name, w, h);
			System::String^ s = UTF8_To_Managed_Str(log);
			cb(s);
		}
		return true;
	}

	if (cb) {
		cb(L"Not covered");
	}

	return false;

}

void  XiaoWeiHelper::MinimizeApp(CallBack^ cb)
{
	HWND xwWnd = ::FindWindowEx(NULL, NULL, NULL, L"惠小微");
	if (xwWnd == NULL) {
		if (cb) {
			cb(L"Don't find Xiaowei window");
		}
		return;
	}

	SendMessage(xwWnd, WM_SYSCOMMAND, SC_MINIMIZE, 0);
	if (cb) {
		cb(L"Xiaowei window has been minimized");
	}
}
bool XiaoWeiHelper::IsMinimized()
{
	HWND xwWnd = ::FindWindowEx(NULL, NULL, NULL, L"惠小微");
	if (xwWnd == NULL) {
		return false;
	}
	return ::IsIconic(xwWnd);
}
